package newspapers.autopublishing;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
import java.util.Set;

import model.Newspaper;

/**
 * Newspapers that publishes messages automatically.
 */
public class AutoNewspaper extends Newspaper {

    /**
     * Autopublishing parameters.
     */
//    ORIGINAL
//    private int id;
//    private ClientControl control;

    public int messageRate = 0;
    public double timeStart;
    public double timeStop;

    public int tSegIndex = 0;

    protected DateFormat mSdf = SimpleDateFormat
            .getTimeInstance(SimpleDateFormat.MEDIUM);

    public boolean active = true;

    //code of interval distribution model used for generating publishing events
    private int distribution;

    // code 0: constant; 1: uniformly distributed length
    private int messageLengthDistribution;

    private int messageLength;

    private double mldStdDeviation;

    //publish topic for autopublisher
    public String currentTopicName = "";
    public String currentTopicURL = "";

    //sequence number of the last sent message
    private int seq = 0;

    /**
     * Constructor for autopublishing newspapers.
     *
     * Opens a connection and creates a session.
     *
     * @param name  name of the newspaper
     * @param username  username to use to connect to the broker
     * @param password  password to use to connect to the broker
     * @param topicPrefix  prefix in the topics of the newspaper
     * @param topics  list of topics to publish to
     * @param ts time segment
     */
    public AutoNewspaper(final String name, final String username,
                         final String password, final String topicPrefix,
                         final Set<String> topics,
//                       int demoId, TimeSeg ts, ClientControl cl) { //ORIGINAL
                         final TimeSeg ts) {

        super(name, username, password, topicPrefix, topics);

//        ORIGINAL
//        this.id = demoId;
//        this.control = cl;

        setRate(ts);
        setDistribution(ts);
        setMessages(ts);

        System.out.println("rate = " + messageRate);
        System.out.println("time start = " + ts.timeStart);
        System.out.println("time stop = " + ts.timeStop);
        //System.out.println("mean rate = " + ts.mean_rate);

        timeStart = ts.timeStart;
        timeStop = ts.timeStop;

        tSegIndex = 0;

        setTopicURL(ts);

    }

    /**
     * Constructor for transforming normal newspapers into autopublishing
     * newspapers.
     *
     * @param newspaper  to transform
     * @param ts  time segment
     */
    public AutoNewspaper(final Newspaper newspaper,
//                       int demoId, TimeSeg ts, ClientControl cl) { //ORIGINAL
                         final TimeSeg ts) {

        //get data from newspaper
        setName(newspaper.getName());
        setClientId(newspaper.getClientId());
        setUsername(newspaper.getUsername());
        setPassword(newspaper.getPassword());
        setTopicPrefix(newspaper.getTopicPrefix());
        setTopics(newspaper.getTopics());

//        ORIGINAL
//        this.id = demoId;
//        this.control = cl;

        setRate(ts);
        setDistribution(ts);
        setMessages(ts);

        System.out.println("rate = " + messageRate);
        System.out.println("time_start = " + ts.timeStart);
        System.out.println("time_stop = " + ts.timeStop);
        //System.out.println("mean rate = " + ts.mean_rate);

        timeStart = ts.timeStart;
        timeStop = ts.timeStop;

        tSegIndex = 0;

        setTopicURL(ts);

    }

    private void setRate(final TimeSeg ts) {
        if (ts.useMeanRate) {
            messageRate = (int) ts.meanRate;
        } else if (ts.maxRate > ts.minRate && ts.minRate >= 0) {
            Random r = new Random();
             double rl = r.nextDouble();
             messageRate
                     = (int) ((ts.maxRate - ts.minRate) * rl + ts.minRate);
        } else {
            messageRate = (int) ts.meanRate;
        }
    }

    public int getDistribution() {
         return distribution;
    }

    private void setDistribution(final TimeSeg ts) {
        if (ts.distribution.equalsIgnoreCase("exp")) {
            distribution = 0;
        } else if (ts.distribution.equalsIgnoreCase("uni")) {
            distribution = 1;
        } else {
            distribution = -1;
        }
    }

    private void setMessages(final TimeSeg ts) {

        if (ts.messageLengthDistribution.equalsIgnoreCase("constant")) {
            messageLengthDistribution = 0;
        } else if (ts.messageLengthDistribution.equalsIgnoreCase("uni")) {
            messageLengthDistribution = 1;
        }

        this.messageLength = ts.messageLength;
        this.mldStdDeviation = ts.mldStdDeviation;

    }

    protected String getTimeAsString() {
        return mSdf.format(new Date());
    }

    /**
     * Set publish topic URL for publish(int i).
     * @param ts  time segment
     */
    public void setTopicURL(final TimeSeg ts) {
        currentTopicName = ts.topicName;
        currentTopicURL = "topic://" + getMOM_EXCHANGE() + "/?routingkey='"
                          + getTopicPrefix() + "." + ts.topicName
                          + "'&exclusive='true'&autodelete='true'";
    }

    /**
     * Update NewspaperQpid object with a TimeSeg in NewspaperConfig.tsegs.
     * @param ts  time segment
     */
    public void updateNewspaperQpid(final TimeSeg ts) {

        tSegIndex++;

        setRate(ts);

        setDistribution(ts);

        setMessages(ts);

        System.out.println("rate = " + messageRate);
        System.out.println("time_start = " + ts.timeStart);
        System.out.println("time_stop = " + ts.timeStop);

        timeStart = ts.timeStart;
        timeStop = ts.timeStop;
        setTopicURL(ts);

    }

    /**
     * Performs publish of random data.
     *
     * @param i  it's supposed to be a timer, but it's not used
     */
    public void onPublish(final int i) {

        //increase sequence number
        seq++;

        try {

//            //Get the publisher
//            TopicPublisherAdapter publisher = getPubForTopic(currentTopicName);
//            //Create the random "text" of the message
//            String text = autoGen.getNameString(message_length,
//                    message_length_distribution, mld_std_deviation);
//            //Create the message to send
//            JMSTextMessage txtMessage
//                    = (JMSTextMessage) getSession().createTextMessage(text);
//            //Set the header of the message
//            txtMessage.setStringProperty("header", "Message " + seq + " from "
//                    + name + " about " + currentTopicName);
//               //Send the message created
//            publisher.publish(txtMessage, DeliveryMode.PERSISTENT,
//                              AbstractJMSMessage.DEFAULT_PRIORITY,
//                              AbstractJMSMessage.DEFAULT_TIME_TO_LIVE);
//            //Print info about the message sent
//            System.out.println("Published message: \"" + txtMessage.getText()
//                               + "\" to " + txtMessage.getJMSDestination());

            //create the random "text" of the message
            String text = AutoGen.getNameString(messageLength,
                    messageLengthDistribution, mldStdDeviation);
            //create the header of the message
            String header = "Message " + seq + " from " + getName() + " about "
                            + currentTopicName;
            //create the properties of the message
            HashMap<String, String> props = new HashMap<String, String>();
            props.put("header", header);
            //publish to main and mirror brokers
            publishMessage(currentTopicName, text, props);

        } catch (Exception e) {
            System.err.println("Error publishing message: " + e);
        }

    }

}
